 
/* 
 * Copyright (C) Ignacio Lucas
 */
 
/*
 *  socket.h, hecho por Ignacio Lucas
 *
 *  Funciones aplicables sobre los sockets.
 *
 *  Ignacio Lucas <ignacio.lucas@gmail.com>
 */
#if !defined(_USE_SOCKET_H)
#define _USE_SOCKET_H

#include "utils/timer_utils.h"

typedef struct s_socket *socket_t;

// Configuraciones especificas de eventos para sockets. El valor particular que tiene los sockets es el timeout.
typedef struct s_socket_config
{
	socket_t st;				// socket sobre el que se configura un evento.

	timer_conf timeout_config;	// en esta estructura el usuario especifica su timeout en el campo timer_delta.

} socket_config;


#include "common.h"
#include "net/net.h"
#include "server_worker.h"

#define SOCKET_INFINITE_TIMEOUT ((timer_delta_t)0)

/*
	Si:
	- socket es no bloqueante y 
	- uso corrutinas y
	- server_worker_job_t esta definido
	
	Esta funcion permite al usuario de sockets definir si read_bytes 
	(read_bytes < asked_bytes) son datos suficientes para procesar o se necesita aplicar un cambio de contexto.
	Si es suficiente, devuelve  1, sino devuelve 0.
*/ 

typedef int (*enough_read_bytes)(char *buf, int read_bytes, int asked_bytes);

// tamanio de la estructura asociada a un socket
size_t socket_get_struct_size();

// aceptacion de una nueva conexion sobre la conexion de servidor st.
socket_t socket_accept(socket_t st);

// cierre de socket.
int socket_close(socket_t st);

// operacion para conectar al socket st con un servidor y puerto TCP. Usa el timeout de connect definido
// en el metodo socket_set_connect_timeout(unsigned int)
int socket_connect(socket_t st, char *server, u_short port);

// timeout = SOCKET_INFINITE_TIMEOUT --> timeout infinito.
// timeout > 0 (milisegundos de timeout).

// devuelve 0 si el valor queda registrado correctamente, o -1 en caso contrario.
int socket_set_connect_timeout(socket_t st, timer_delta_t timeout);
timer_delta_t socket_get_connect_timeout(socket_t st);

int socket_set_read_timeout(socket_t st, timer_delta_t timeout);
timer_delta_t socket_get_read_timeout(socket_t st);

int socket_set_write_timeout(socket_t st, timer_delta_t timeout);
timer_delta_t socket_get_write_timeout(socket_t st);

// destruccion de un socket
int socket_destroy(socket_t st);

// obtiene el file-descriptor asociado al socket.
int socket_get_fd(socket_t st);

// indica con 1 si se registraron eventos sobre el socket, 0 caso contrario
int socket_set_registered_events(socket_t st, int rev);

// devuelve si el socket asociado ya tiene eventos configurados.
int socket_get_registered_events(socket_t st);

// devuelve la tarea sobre la que se esta usando este socket.
server_worker_job_t socket_get_server_worker_job(socket_t st);

// crea un socket de un DOMINIO, TIPO y PROTOCOLO particular.
socket_t socket_init(int domain, int type, int protocol);

// crea un socket como en socket_init, especificando ademas la tarea asociada.
socket_t socket_init_with_job(int domain, int type, int protocol, server_worker_job_t jobt);

// devuelve la funcion de callback asociada al socket, utilizada para saber si la cantidad de bytes leidos es suficiente.
enough_read_bytes socket_get_read_callback(socket_t st);

// setea la funcion de callback asociada al socket, utilizada para saber si la cantidad de bytes leidos es suficiente.
int socket_set_read_callback(socket_t st, enough_read_bytes read_callback);

// devuelve 1 si el socket esta abierto, 0 caso contrario.
int socket_is_open(socket_t st);

// devuelve 1 si el par TCP conectado ha cerrado la conexion, 0 caso contrario.
int socket_peer_closed(socket_t st);

// devuelve el ultimo error generado en alguna operacion sobre el socket
int socket_get_last_error(socket_t st);

// permite configurar a un socket servidor TCP para que atienda conexiones en una IP y puerto particular, con un backlog TCP configurado en queue_size.
int socket_listen(socket_t st, char *listen_ip, int listen_port, int queue_size);

// permite leer del socket.
int socket_read(socket_t st, char *ptr, int maxlong);

// permite reconfigurar un objeto socket con nuevos valores de DOMINIO, TIPO, PROTOCOLO y tarea asociada.
socket_t socket_reuse_instance(socket_t st, int domain, int type, int protocol, server_worker_job_t jobt);

// setea la tarea asociada al socket.
int socket_set_server_worker_job(socket_t st, server_worker_job_t jobt);

// escritura sobre el socket.
int socket_write(socket_t st, char *ptr, int nbytes);

#endif
